package jmetal.util;

public class MatrixUtil {

	/**
	 * 返回两个向量的距离
	 * @param idealPoint
	 * @param normSolutionVector
	 * @return
	 */
	public static double distance(double[] vector1, double[] vector2) {
		double distance = 0;
		if(vector1.length == vector2.length){
			double[] differVect = new double[vector1.length];
			for(int i = 0;i<vector1.length;i++){
				differVect[i] = vector1[i]-vector2[i];
			}
			distance = norm(differVect);
			return distance;
		}else throw new JMRuntimeException("the length of vectors must be the same!");
	}

	/**
	 * 返回向量vector的模
	 * @param vector
	 * @return
	 */
	public static double norm(double[] vector) {
		double norm = 0;
		for(int i = 0;i<vector.length;i++){
			norm=norm+vector[i]*vector[i];
		}
		return Math.sqrt(norm);
	}
	
	/**
	 * 根据vector的长度length返回length-Norm
	 * @param vector
	 * @return
	 */
	public static double lNorm(double[] vector){
		double l = vector.length;
		double norm = 0;
		for(int i = 0;i<vector.length;i++){
			norm=norm+Math.pow(vector[i], l);
		}
		return Math.pow(norm, 1/l);
	}
	
	/**
	 * 返回vector1和vector2的角度值
	 * @param vector1
	 * @param vector2
	 * @return
	 */
	public static double angle(double[] vector1, double[] vector2){
		
		if (vector1.length == vector2.length) {
			double innerProd = dot(vector1, vector2);
			double tempAngle = innerProd / (norm(vector1) * norm(vector2));
			return Math.acos(tempAngle);
		} else
			throw new JMRuntimeException("the length of vectors must be the same!");
	}
	
	/**
	 * 返回余弦值
	 * @param vector1
	 * @param vector2
	 * @return
	 */
	public static double cos(double[] vector1, double[] vector2){
		if (vector1.length == vector2.length) {
			return dot(vector1, vector2)/(norm(vector1) * norm(vector2));
		} else
			throw new JMRuntimeException("the length of vectors must be the same!");
	}

	/**
	 * 内积
	 * @param vector1
	 * @param vector2
	 * @return
	 */
	private static double dot(double[] vector1, double[] vector2) {
		double innerProd = 0;
		for (int dim = 0; dim < vector1.length; dim++) {
			double x1 = vector1[dim];
			double x2 = vector2[dim];
			innerProd = innerProd + (x1 * x2);
		}
		return innerProd;
	}

	public static double sin(double[] objectives, double[] objectives2) {
		double cos2 = Math.pow(cos(objectives,objectives2), 2);
		if(cos2>1.0){
			cos2 = 1.0;
		}
		return Math.sqrt(1.0-cos2);
	}

	public static double manhattanNorm(double[] objectives) {
		double distance = 0.0;
		for(int i = 0;i<objectives.length;i++)
			distance+=objectives[i];
		return distance;
	}
}
